/*
 * MensajeAplicacion.cpp
 *
 *  Created on: 31/01/2010
 *      Author: San Martín, Matías I.
 */

#include "MensajeAplicacion.h"

#include <iostream>

#include "DatosMensajeFactory.h"

namespace aplicacion {

std::ostream &operator<<( std::ostream &stream, const MensajeAplicacion &obj )
{
	return stream << "MensajeAplicacion("<< obj.getTamanio() <<"):"
			<< obj._encabezado << "||"
			<< obj.getDatos().toString();
}

MensajeAplicacion::MensajeAplicacion() : _datos(NULL) {
}

MensajeAplicacion::MensajeAplicacion (const Encabezado& encabezado,
									DatosMensaje* datos)
	: _encabezado (encabezado), _datos (datos)

{
	this->actualizarTamanio();
}

MensajeAplicacion::~MensajeAplicacion() {
	if (_datos)
		delete _datos;
}

void MensajeAplicacion::setDatos(DatosMensaje* datos)
{
	if (_datos)
		delete _datos;

	_datos = datos;
	this->actualizarTamanio();
}

void MensajeAplicacion::setEncabezado(const Encabezado& encabezado)
{
	_encabezado = encabezado;
	this->actualizarTamanio();
}

Encabezado& MensajeAplicacion::getEncabezado()
{
	return _encabezado;
}
DatosMensaje& MensajeAplicacion::getDatos()
{
	return *_datos;
}

const DatosMensaje& MensajeAplicacion::getDatos() const
{
	return *_datos;
}

void MensajeAplicacion::actualizarTamanio()
{
	this->setTamanio(_encabezado.getTamanio() + _datos->getTamanio());
}

/**
 * @throws IOExcepcion @see File#writeAll
 */
size_t MensajeAplicacion::save (int fd) const
{
	//TODO MANEJO DE ERRORES
	size_t guardado = 0;

	//se guarda el encabezado
	guardado += _encabezado.save(fd);

	//se guardan los datos
	guardado += _datos->save(fd);

	return guardado;
}

/**
 * @throws IOExcepcion @see File#writeAll
 */
 size_t MensajeAplicacion::load (int fd)
 {
	 //TODO MANEJO DE ERRORES
	 size_t cargado = 0;

	 //se carga el encabezado
	 cargado += _encabezado.load(fd);

	 //se cargan los datos (segun que tipo son)
	 _datos = DatosMensajeFactorySingleton::instance().create(_encabezado.getTipoMensaje());
	 cargado += _datos->load(fd);

	 //se actualiza el tamaño segun lo cargado
	 this->setTamanio(cargado);

	 return cargado;

 }

 size_t MensajeAplicacion::saveToArray (uint8_t* arr) const
 {
 	size_t guardado = 0;

 	//se guarda el encabezado
 	guardado = _encabezado.saveToArray(arr);
 	if(guardado==0) {
 		return 0;
 	}
 	arr += guardado;

 	//se guardan los datos
 	guardado = _datos->saveToArray(arr);
 	if(guardado==0) {
 		return 0;
 	}

 	return this->getTamanio();
 }

 size_t MensajeAplicacion::loadFromArray (const uint8_t* arr)
 {
	 size_t cargado;

	 //se carga el encabezado
	 cargado = _encabezado.loadFromArray(arr);
	 if(cargado==0) {
		 return 0;
	 }
	 arr += cargado;

	 //se cargan los datos (segun que tipo son)
	 _datos = DatosMensajeFactorySingleton::instance().create(
			 _encabezado.getTipoMensaje());
	 cargado = _datos->loadFromArray(arr);
	 if(cargado==0) {
		 return 0;
	 }

	 //se actualiza el tamaño segun lo cargado
	 this->setTamanio(_encabezado.getTamanio() + _datos->getTamanio());

	 return this->getTamanio();
 }

}//namespace aplicacion
